// 录音页面
const { request, uploadFile2} = require('../../utils/request')
const SpeechTranscription = require('../../aliUtils/st.js')
const sleep = require('../../aliUtils/util.js').sleep
const getToken = require('../../aliUtils/token.js').getToken
const {
  formatSeconds,
} = require('../../utils/util')
const AKID = 'LTAI5tEiVB1fqnVmo2ctMYi2'
const AKKEY = '1USsGGtonGOgPvSNj71kefjTxDT6I7'
const aliSpeechUrl = 'wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1'
const APPKEY = '8w519vsOlGEdq8LH'
// 语音转文字实例
let st:any = null

//Page Object
let recorderManager = null as any

let timeHander = null as any
let curSeconds = 0
let topTotalSeconds = 60
let requestTimeHandler = null as any
let hasShowShareDialogKey = 'index/hasShowShareDialog'
let recordResTimeHandler = null as any
let isCancelRecord = false
let innerAudioContext = null as any
let llmRequestTimes = 0
let pageStatus = 'active'
let llmTimeHander = null as any
//Page Object
Page({
  data: {
    inRecord: false,
    stResult: '',
    tempStResult:'',
    curTimeStr: formatSeconds(curSeconds),
    limitTimeStr: formatSeconds(topTotalSeconds),
    aliToken: '',
    recordStep:0, // 0是录音阶段 1是ai处理阶段 2是处理完成
    aiStep:0, // ai处理的步骤
    aiOptimizeResult:{
      title:'',
      content:''
    },
    audioTempPath:'',
    audioServerPath:'',
    playingAudioUrl:'', // 
    hasShowShareDialog:false,
    submitBtnBgWidth:'0%',
    recordExceedTimeDialogVisible:false,
    templateTipDialogVisible:false,
    currentRecord:null,
    recordType:1, // 1是实时录音 2是录音文件
    voiceAnimate:true,
    loadingVisible:false,
    showPureTime:true,
    countTimeNum:11,
    emptyVoiceDialogVisible:false
  },
  //options(Object)

  onShow(){
    pageStatus = 'active'
    // 播放提示音，播放完成后开始录音
    this.playTipVoice()
    this.initTimeData()
    
    if(!this.data.aliToken){
      this.getAliToken()
    }
    this.getShareDialogStatus()
    clearInterval(recordResTimeHandler)
    recordResTimeHandler = null
    clearTimeout(requestTimeHandler)
    requestTimeHandler = null
    isCancelRecord = false
  },

  async unloadAndHideCallback(){
    pageStatus = 'inactive'
    if(innerAudioContext){
      innerAudioContext.destroy()
      innerAudioContext = null
    }
    if(st){
      console.log('st shutdown')
      st.close()
      st.shutdown()
    }
    st = null
    
    console.log("onUnload")
    this.recordFinish()
    this.pageHideCallback()
    if(this.data.audioTempPath){
      // 删除本地文件
      wx.removeSavedFile({
        filePath: this.data.audioTempPath
      })
    }
  },

  async onUnload() {
    this.unloadAndHideCallback()
  },
  async onHide(){
    this.unloadAndHideCallback()
  },
  initStartRecord(){
    // 获取用户录音时长
    
    this.stopAllAudio()
    // if(this.data.recordStep === 0 ){
    this.startRecord()
    // }
  },
  playTipVoice(){
    if(this.data.recordStep !== 0 ){
      return 
    }
    if(innerAudioContext){
      innerAudioContext.destroy()
    }
    let that = this as any
    innerAudioContext = wx.createInnerAudioContext({
      useWebAudioImplement: false 
    }) 
    innerAudioContext.src = 'https://wanhuhealth.oss-cn-beijing.aliyuncs.com/static/note-miniProgram/ding.mp3'
    innerAudioContext.play()
    innerAudioContext.onEnded(()=>{
      // 开始录音
      innerAudioContext.destroy()
      that.initStartRecord()  
    })
  },
  pageHideCallback(){
    clearTimeout(llmTimeHander)
    clearInterval(recordResTimeHandler)
    clearInterval(timeHander)
    clearTimeout(requestTimeHandler)
    requestTimeHandler= null 
  },
  showEmptyVoiceDialog(){
    this.setData({
      emptyVoiceDialogVisible: true
    })
  },
  hideEmptyVoiceDialog(){
    this.setData({
      emptyVoiceDialogVisible: false
    })
  },
  showLoading(){
    this.setData({
      loadingVisible:true
    })
  },
  hideLoading(){
    this.setData({
      loadingVisible:false
    })
  },
  showExceedTimeDialog(){
    this.setData({
      recordExceedTimeDialogVisible:true
    })
  },
  hideExceedTimeDialog(){
    this.setData({
      recordExceedTimeDialogVisible:false
    })
  },
  showTemplateTipDialog(){
    this.setData({
      templateTipDialogVisible:true
    })
  },
  hideTemplateTipDialog(){
    this.setData({
      templateTipDialogVisible:false
    })
  },
  initTimeData(){
    let userInfo = wx.getStorageSync('userInfo')
    if(userInfo){
      topTotalSeconds = userInfo.recordingDuration,
      this.setData({
        limitTimeStr:formatSeconds(topTotalSeconds)
      })
    }
  },
  restartRecord(){
    this.recordFinish()
    this.startRecord()
  },
  playRecordAudio(){
    // console.log('playRecordAudio')
    // console.log('this.data.audioTempPath:',this.data.audioTempPath)
    const innerAudioContext = wx.createInnerAudioContext({
      useWebAudioImplement: true 
    })
    innerAudioContext.play()
    innerAudioContext.src = this.data.audioTempPath
    innerAudioContext.onEnded(()=>{
      innerAudioContext.destroy()
    })
  },
  startCountTime(){
    let that = this
    if(timeHander){
      clearInterval(timeHander)
    }
    
    curSeconds = 0
    timeHander = setInterval(()=>{
      curSeconds++
      // console.log('curSeconds:',curSeconds)
      if(curSeconds >= topTotalSeconds){
        clearInterval(timeHander)
        that.recordFinish()
        that.setData({
          submitBtnBgWidth: '100%',
          curTimeStr:formatSeconds(topTotalSeconds),
        })
        if(that.data.recordType ===1 ){
          // 实时录音,录音结束，直接ai处理
          that.startAiOptimize()
        }
        // that.showExceedTimeDialog()
        // wx.showModal({
        //   title:'提示',
        //   content:'时间到，录音结束！',
        //   confirmText:'提交完成',
        //   cancelText:'重新录制',
        //   showCancel:true,
        //   success:(res)=>{
        //     if(res.confirm){
        //       that.startAiOptimize()
        //     }else {
        //       that.restartRecord()
        //     }
            
        //   }
        // })
        
      }else {
        if(topTotalSeconds - curSeconds <= 10){
          let countTimeNum = this.data.countTimeNum - 1
          this.setData({
            showPureTime:false,
            countTimeNum
          })
        }
        
        that.setData({
          submitBtnBgWidth: (Math.floor(curSeconds / topTotalSeconds * 100)) +'%',
          curTimeStr:formatSeconds(curSeconds),

        })
      }
    },1000)
  },
  stopCountTime(){
    if(timeHander){
      clearInterval(timeHander)
    }
  },
  async initSpeechTranscription() {
    let that = this
    // console.log('initSpeechTranscription st:',st)
    if(st){
      return 
    }
    
    st = new SpeechTranscription({
      url: aliSpeechUrl,
      appkey: APPKEY,
      token: this.data.aliToken
    })

    st.on('started', (msg:string) => {
      // console.log('Client recv started',msg)
      // this.setData({
      //   stResult: msg
      // })
    })

    st.on('changed', (res:any) => {
      // console.log('Client recv changed:', res)
      if(res){
        try {
          let resObj = JSON.parse(res)
          // console.log('resObj:',resObj)
          if(resObj.payload){
            that.setData({
              tempStResult:resObj.payload.result,
              recordScollViewId:'scrollTarget1'
            },()=>{
              setTimeout(()=>{
                that.setData({
                  recordScollViewId:'scrollTarget1'
                },100)
              })
              
            })
          }
        } catch (error) {
          console.error(error)
        }
      }
    })

    st.on('completed', (msg:string) => {
      // console.log('Client recv completed:', msg)
      // this.setData({
      //   stResult: msg
      // })
    })

    st.on('begin', (res:string) => {
      // 句子开始
      // console.log('Client recv sentenceBegin:', res)
     
    })

    st.on('end', (res:string) => {
      // console.log('Client recv sentenceEnd:', res)
      // 一句话结束
      // this.setData({
      //   stResult: msg
      // })
      if(res){
        try {
          let resObj = JSON.parse(res)
          // console.log('resObj:',resObj)
          if(resObj.payload){
            that.setData({
              tempStResult:'',
            },()=>{
              that.setData({
                stResult: that.data.stResult + resObj.payload.result
              })
            })
          }
        } catch (error) {
          console.error(error)
        }
      }
    })

    st.on('closed', () => {
      console.log('Client recv closed')
    })

    st.on('failed', (msg:string) => {
      // console.log('Client recv failed:', msg)
      // this.setData({
      //   stResult: msg
      // })
    })
    
  },
  // 处理录音并发,返回true，表示可以实时录音，false就是只能录音
  addRecordConCurrent(){
    // 添加录音并发 1=正常 2=已达上限 
    return new Promise(resolve=>{
      request({
        url:'/records/add-real-time?key='+wx.getStorageSync('openid'),
        method:'post',
        success(data:any){
          // 1=正常 2=已达上限
          if(data.status === 1 ){
            // 可以实时录音
            resolve(true)
          }else {
            resolve(false)
          }
        },
        fail(){
          resolve(false)
        }
      })
    })
    
  },
  removeRecordConCurrent(){
    let openid = wx.getStorageSync('openid')
    if(openid){
      // 获取录音并发
      request({
        url:'/records/remove-real-time?key='+openid,
        method:'post',
        success(data:any){
          console.log('删除录音并发')
        },
        fail(error:any){
          console.log('删除录音并发失败：',error)
        }

      })
    }
    
  },
  stopTouchmove(event:any){
    return false
  },
  initRecord(){
    console.log('initRecord')
    if(!recorderManager){
      recorderManager = wx.getRecorderManager()
      recorderManager.onStart(()=>{
        console.log('开始录音')
      })
      recorderManager.onFrameRecorded(async (res:any) => {
        // console.log('onFrameRecorded:')
        if (res.isLastFrame) {
          console.log('recorderManager isLastFrame')
          // 录音超时
          // this.completeRecord()
        }

        if (st && this.data.inRecord) {
          // console.log('send ' + res.frameBuffer)
          st.sendAudio(res.frameBuffer)
        }
        
      })

      recorderManager.onStop(async (res: any) => {
        console.log('onStop pageStatus:',pageStatus)
        if(pageStatus ==='active'){
          console.log('结束录音')
          if (res.tempFilePath) {
            let uploadResUrl = await uploadFile2(res.tempFilePath)
            console.log('uploadResUrl :',uploadResUrl)
            this.setData({
              audioTempPath:res.tempFilePath,
              audioServerPath:uploadResUrl
            })
        }
        }
        
        
      })
    }
    
  },
  async getAliToken() {
    let token = await getToken(AKID, AKKEY)
    // console.log('getAliToken:',token)
    this.setData({
      aliToken: token
    })
    // console.log('alitoken:',token)
    // this.initSpeechTranscription()
    // this.initRecord()
    
  },

  stopAllAudio(){
    this.setData({
      playingAudioUrl:'stopAll'
    })
  },

  jumpBackPage() {
    wx.reLaunch({
      url:'/pages/index/index'
    })
  },
  async startRecord(){
    // 开始录音，可能是实时语音识别，也可以只是录音
    let canRealTimeRecord = await this.addRecordConCurrent()
    // canRealTimeRecord = false
    if(canRealTimeRecord){
      this.startRealTimeRecord()
      this.setData({
        recordType:1
      })
    }else {
      this.startRecordFile()
      this.setData({
        recordType:2
      })
    }
  },
  startRecordFile(){
    console.log('startRecordFile')
    let that = this as any
    if (this.data.inRecord) {
      // 正在记录，避免重复打开多次
      return
    }
    this.initRecordState()
    // 开始录音文件
    if(!recorderManager){
      recorderManager = wx.getRecorderManager()
    }
    this.startCountTime()
    this.setData({
      inRecord:true
    })
    recorderManager.onStart(()=>{
      console.log('开始录音')
    })
    recorderManager.onStop(async (res: any) => {
      console.log('onStop pageStatus:',pageStatus)
      console.log('结束录音 isCancelRecord:',isCancelRecord)
      if(pageStatus !=='active'){
        return
      }
      if(isCancelRecord){
        return 
      }
      if (res.tempFilePath) {
        let uploadResUrl = await uploadFile2(res.tempFilePath)
        console.log('uploadResUrl :',uploadResUrl)
        that.setData({
          audioTempPath:res.tempFilePath,
          audioServerPath:uploadResUrl
        })
        // 添加记录
        clearInterval(recordResTimeHandler)
        // that.submitRecordResult(that.getCurRecordData.bind(that))
        that.submitRecordResult()
      }
      
    })
    recorderManager.start({
      duration: topTotalSeconds * 1000,
      sampleRate: 16000,
      format: 'mp3',
      frameSize: 4,
      encodeBitRate: 96000, 
      numberOfChannels: 1 
    })
    
    
  },
  getCurRecordData(recordData:any){
    console.log('getCurRecordData recordData:',recordData)
    let that = this as any
    if(recordResTimeHandler){
      clearInterval(recordResTimeHandler)
    }
    
    this.showLoading()
    recordResTimeHandler = setInterval(()=>{
      request({
        url:'/records/'+recordData.id,
        success(rData:any){
          console.log('rData:',rData)
          // 已完成
          if(rData.status ===2){
            clearInterval(recordResTimeHandler)
            that.hideLoading()
            that.setData({
              recordStep:2,
              currentRecord:rData,
              aiOptimizeResult:{
                title: rData.title,
                content: rData.content
              }
            })
          }else if(rData.status ===3){
            clearInterval(recordResTimeHandler)
            that.hideLoading()
            // 内容为空
            that.showEmptyVoiceDialog()
            setTimeout(()=>{
              that.hideEmptyVoiceDialog()
              that.jumpBackPage()
            },2000)
            
            
          }
        }
      })
    },1000)
  },
  async startRealTimeRecord() {
    // 开始录音
    console.log('开始录音 aliToken:',this.data.aliToken)
    if(!this.data.aliToken){
      await this.getAliToken()
    }
    // 开始录音
    if(!st){
      this.initSpeechTranscription()
    }
    if(!recorderManager){
      this.initRecord()
    }
    // 
    // console.log('inRecord:',this.data.inRecord)
    if (this.data.inRecord) {
      // 正在记录，避免重复打开多次
      return
    }

    this.initRecordState()
    this.startCountTime()
    
    await st.start(st.defaultStartParams())
    
    recorderManager.start({
      duration: topTotalSeconds * 1000,
      sampleRate: 16000,
      format: 'mp3',
      frameSize: 4,
      encodeBitRate: 96000, 
      numberOfChannels: 1 
    })
    this.setData({
      inRecord:true
    })
    
  },
  initRecordState(){
    // 把录音相关状态初始化
    curSeconds = 0
    this.setData({
      stResult:'',
      tempStResult:'',
      recordStep:0,
      aiStep:0,
      aiOptimizeResult:{
        title:'',
        content:''
      },
      audioTempPath:'',
      curTimeStr: formatSeconds(curSeconds),
      submitBtnBgWidth:'0%',
      showPureTime:true,
      countTimeNum:11  // 倒计时提示显示的时间
    })
    
  },

  judgeShowTemplateDialog(){
    let that = this as any
    // 先保存
    that.submitRecordResult(()=>{
      if(this.data.hasShowShareDialog){
        // 已经显示过提示弹窗，直接跳模板页
        this.jumpTemplatePage()
      }else {
        that.showTemplateTipDialog()
        this.setData({
          hasShowShareDialog:true
        })
        wx.setStorage({
          key:hasShowShareDialogKey,
          data:true
        })
      }
    })
  },
  getShareDialogStatus(){
    let hasShowShareDialog = wx.getStorageSync(hasShowShareDialogKey) || false
    this.setData({
      hasShowShareDialog:hasShowShareDialog
    })
  },
  jumpTemplatePage(){
    console.log('currentRecord:',this.data.currentRecord)
    let recordData = this.data.currentRecord
    wx.redirectTo({
      url:'/pages/template/template?id='+recordData.id+'&shareChannel=3'
    })

    wx.setStorageSync('/index/templateData',{
      title:recordData.title,
      content:recordData.content
    })
    
  },
  submitRecordResult(callback:Function){
    let that = this as any
    console.log('requestTimeHandler:',requestTimeHandler)
    if(!requestTimeHandler){
      requestTimeHandler = setTimeout(()=>{
        requestTimeHandler = null
      },1000)

      this.stopAllAudio()
      // 保存ai生成的结果
      console.log('this.data:',this.data)
      let reqData = {
        type: this.data.recordType,
        title: this.data.aiOptimizeResult.title || '记录生成中',
        content: this.data.aiOptimizeResult.content || '非常抱歉，访问人数太多，我们会尽快为您生成结果',
        originalContent: this.data.stResult,
        voiceAddress:this.data.audioServerPath,
        voiceDuration: curSeconds,
      }
      console.log('reqData:',reqData)
      request({
        url:'/records',
        method:'POST',
        data:reqData,
        success:(recordData:any)=>{
          console.log('recordData:',recordData)
          this.setData({
            currentRecord:recordData
          })
          // if(typeof callback === 'function'){
          //   callback(recordData)
          // }else {
          //   this.jumpBackPage(recordData)
          // }
          wx.redirectTo({
            url:'/pages/recordResult/recordResult?id='+recordData.id
          })
        },
        complete(){
          requestTimeHandler = null
        }
      })
      
    }
  },

  playThisAudio(event:any){
    // console.log('playThisAudio:',event.detail.audioUrl)
    this.setData({
      playingAudioUrl: event.detail.audioUrl
    })
  },
  async recordFinish() {
  
    this.stopCountTime()
    // 录音结束
    
    this.setData({
      aliToken:'',
      inRecord: false,
      voiceAnimate:false,
      countTimeNum:11,
      showPureTime:true,
    })
    // 只有实时录音才调用stop
    if (recorderManager) {
      recorderManager.stop()
    }
    recorderManager = null
    if(st && st._client){
      console.log('recordFinish st close：',st)
      st.close()
    }
    // 删除录音并发
    this.removeRecordConCurrent()
  },
  async getLLMText(resolve:Function){
    
    let that = this as any
    request({
      url:'/llm/sendMsgToLLM',
      method:'POST',
      data:{
        contentMsg: that.data.stResult,
      },
      success:(respData:any)=>{
        // alert('startAiOptimize res:'+JSON.stringify(res.data))
        let result = {} as any
        if(typeof respData ==='string'){
          result.title = respData
          result.content = respData
        }else {
          result = {
            title: respData.title,
            content: respData.content
          }
        }
        that.setData({
          aiOptimizeResult: result
        })
        resolve(null)
      },
      fail:(error:any)=>{
        llmRequestTimes +=1
        console.log('startAiOptimize error:',error)
        // wx.showModal({
        //   title:'',
        //   content:'调用AI失败,请稍后再试!'+JSON.stringify(error),
        //   showCancel:false,
        //   confirmText:'确定',
        //   success:()=>{
        //     that.cancelRecord()
        //   }
        // })
        // let titleList = that.data.stResult.split(/,|，|。|;/)
        // that.setData({
        //   aiOptimizeResult: {
        //     title: titleList && titleList[0] || that.data.stResult,
        //     content: that.data.stResult
        //   }
        // })
        // resolve(null)
        console.log('llmRequestTimes:',llmRequestTimes)
        if(llmRequestTimes>=5){
          // let hasShowModalError = wx.getStorageSync('hasShowModalError') || false
          // if(!hasShowModalError){
          //   wx.showModal({
          //     title:'',
          //     content:'调用AI失败,请稍后再试!'+JSON.stringify(error),
          //     showCancel:false,
          //     confirmText:'确定',
          //     success:()=>{
          //       that.cancelRecord()
          //     }
          //   })
          //   wx.setStorageSync('hasShowModalError',true)
          // }
          
          resolve(null)
        }else {
          llmTimeHander = setTimeout(()=>{
            that.getLLMText(resolve)
          },5000)
          // that.getLLMText(resolve)
        }
      },
    })
  },
  startAiOptimize(){
    let that = this
    if(this.data.recordStep!==0){
      that.jumpBackPage()
      return 
    }
    if(!(that.data.stResult.trim())){
      // wx.showModal({
      //   title:'',
      //   content:'录音内容不能为空,请重新录制',
      //   showCancel:false,
      //   confirmText:'确定',
      //   success:()=>{
      //     that.cancelRecord()
      //   }
      // })
      that.recordFinish()
      that.jumpBackPage()
      return 
    }
    if(pageStatus  === 'inactive' || isCancelRecord){
      return 
    }
    // 实时录音
    if(this.data.recordType === 1){
      this.setData({
        recordStep:1
      })
    }
    
    let aiStep = this.data.aiStep
    let promise1 = new Promise(resolve=>{
      let timeHandler = setInterval(()=>{
        if(aiStep < 3){
          that.setData({
            aiStep:aiStep++
          })
        }else {
          clearInterval(timeHandler)
          resolve(null)
        }
      },500)
    })
    let promise2 = new Promise(resolve=>{
      that.getLLMText(resolve)
    })

    Promise.all([promise1,promise2]).then(()=>{
      that.aiOptimizeFinish()
    })
    
    
  },
  aiOptimizeFinish(){
    // this.setData({
    //   recordStep:2
    // })
    // 自动保存
    this.submitRecordResult()
  },
  completeRecord(){
    console.log('completeRecord inRecord:',this.data.inRecord)
    if(this.data.inRecord){
      // 完成录音
      this.recordFinish()

      if(this.data.recordType === 1){
        // 实时录音
        if(!(this.data.stResult.trim()) && !!this.data.tempStResult){
          this.setData({
            stResult:this.data.tempStResult
          },()=>{
            this.startAiOptimize()
          })
        }else {
          // 开始ai处理
          this.startAiOptimize()
        }
      }else {
        // 非实时录音，录音完成后会自动执行后续步骤
        console.log('非实时录音')
        // 处理逻辑放在了recorderManager.onStop 中
      }
    }
  },
 
  cancelRecord(){
    
    console.log('cancelRecord')
    isCancelRecord = true
    recorderManager.onStop(()=>{
      console.log('cancelRecord 结束录音')
    })
    this.stopAllAudio()
    // 主动取消录音,隐藏录音层
    this.jumpBackPage()
    
  }
}); 
